library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity usb_transceiver is
	Port ( 	clk : in  STD_LOGIC;
		
			-- jtag
			TDI : in std_logic;   		--// CPLD -> FPGA (data in)
			TCK : in std_logic;  		--// CPLD -> FPGA (clk)
			TCS : in std_logic;  		--// CPLD -> FPGA (CS)
			TDO : out std_logic;  		--// FPGA -> CPLD (data out)
			
			-- incoming
			in_valid : out std_logic;
			in_value : out unsigned(7 downto 0);
			
			-- out fifo
			out_we : in std_logic;
			out_full : out std_logic;
			out_empty : out std_logic;
			out_data : in unsigned(7 downto 0);
			out_words : out std_logic_vector(8 downto 0)
		);		 
end usb_transceiver;

		

architecture Behavioral of usb_transceiver is
	
	-- out fifo
	signal out_re : std_logic;
	signal out_value : std_logic_vector(7 downto 0);
	signal bytes_in_fifo : std_logic_vector(8 downto 0);
	
	
	-- regs
	signal clock_detect : unsigned(1 downto 0) := "11";
	signal receive_counter : unsigned(2 downto 0) := (others => '0');
	signal receive_buffer : unsigned(7 downto 0) := (others => '0');
	signal received_valid_buffer : std_logic := '0';
	signal timeout : unsigned(6 downto 0) := (others => '0');
	signal bits_send : unsigned(2 downto 0) := "000";
	signal transmit_buffer : unsigned(7 downto 0) := (others => '0');
	
	
	component usb_transmit_fifo
	PORT
	(
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		rdreq		: IN STD_LOGIC ;
		wrreq		: IN STD_LOGIC ;
		empty		: OUT STD_LOGIC ;
		full		: OUT STD_LOGIC ;
		q			: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
		usedw		: OUT STD_LOGIC_VECTOR (8 DOWNTO 0)
	);
	end component;
	
	
begin

	
	usb_transmit_fifo_inst : usb_transmit_fifo PORT MAP (
		clock	 => clk,
		data	 => std_logic_vector(out_data),
		rdreq	 => out_re,
		wrreq	 => out_we,
		empty	 => out_empty,
		full	 => out_full,
		q	 	 => out_value,
		usedw    => out_words
	);


	
	process (clk)
	begin
		if rising_edge(clk) then
		
			received_valid_buffer <= '0';			-- gets overwritten
			
			timeout <= timeout +1;								-- no posedge or tcs high -> increase timeout
			if timeout=(6 downto 0 => '1')  then				
				receive_counter <= (others => '0');		
				bits_send <= "000";							-- 21bit counter...it works but not nice
			end if;
		
			if tcs='0' then				-- enable to FPGA
				
				clock_detect <= clock_detect(0) & tck;	
		
				if clock_detect = "01" then									-- detect safe posedges on tck
					timeout <= (others => '0');								-- set timout as data is found
					receive_counter <= receive_counter +1;
					receive_buffer <= tdi & receive_buffer(7 downto 1);		-- shift in the data
					if receive_counter="111" then
						received_valid_buffer <= '1';						-- set data valid -> wren on incoming fifo for 1 clock
					end if;									
				end if;
				
				if clock_detect="01" then		-- react on negedge here as data must already be loaded at posedge
					timeout <= (others => '0');	
					bits_send <= bits_send +1;
					transmit_buffer <= '1' & transmit_buffer(7 downto 1);	-- shift data out
					if bits_send="000" then
						transmit_buffer <= unsigned(out_value);						-- fetch new data
					end if;
				end if;
				
			end if;
			
		end if;
	end process;
	
	
	in_valid <= received_valid_buffer;
	in_value <= receive_buffer;
	
	out_re <= '1' when bits_send="110" and clock_detect = "10" else '0';
	
	tdo <= transmit_buffer(0);
	
	

end Behavioral;





